<template>
  <div
    class="map-container"
    ref="container"
    @mousedown="handleMouseDown"
    @touchstart="handleTouchStart"
    @wheel="handleWheel"
  >
    <!-- 地图图层 -->
    <div
      class="map-layer"
      ref="mapLayer"
      :style="mapStyle"
    >
      <img
        :src="backgroundSrc"
        alt="地图背景"
        @load="handleImageLoad"
        @dragstart.prevent
      />

      <!-- 标记点层 -->
      <div class="markers-container" v-if="markers && markers.length">
        <div
          v-for="marker in markers"
          :key="marker.id"
          class="marker-wrapper"
          :style="getMarkerStyle(marker)"
          @click.stop="handleMarkerClick(marker)"
          @mousedown.stop
          @touchstart.stop
        >
          <MapMarker
            :marker="marker"
            :type="marker.type"
            :show-label="marker.showLabel"
            :show-pulse="marker.showPulse"
            :is-active="activeMarkerId === marker.id"
          />
        </div>
      </div>
    </div>

    <!-- 缩放控件 -->
    <div class="zoom-controls">
      <button
        class="zoom-btn zoom-in"
        @click="zoomIn"
        @touchstart.stop
        @mousedown.stop
        :disabled="currentZoom >= maxZoom"
        title="放大"
      >
        <svg width="18" height="18" viewBox="0 0 24 24" fill="none">
          <circle cx="11" cy="11" r="8" stroke="currentColor" stroke-width="2"/>
          <path d="M21 21L16.65 16.65" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
          <path d="M11 8V14M8 11H14" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
        </svg>
      </button>

      <div class="zoom-level">
        <span class="zoom-text">{{ Math.round(currentZoom * 100) }}%</span>
      </div>

      <button
        class="zoom-btn zoom-out"
        @click="zoomOut"
        @touchstart.stop
        @mousedown.stop
        :disabled="currentZoom <= minZoom"
        title="缩小"
      >
        <svg width="18" height="18" viewBox="0 0 24 24" fill="none">
          <circle cx="11" cy="11" r="8" stroke="currentColor" stroke-width="2"/>
          <path d="M21 21L16.65 16.65" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
          <path d="M8 11H14" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
        </svg>
      </button>

      <button
        class="zoom-btn zoom-reset"
        @click="resetZoom"
        @touchstart.stop
        @mousedown.stop
        :disabled="currentZoom === defaultZoom"
        title="重置缩放"
      >
        <svg width="16" height="16" viewBox="0 0 24 24" fill="none">
          <path d="M1 4V10H7" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
          <path d="M23 20V14H17" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
          <path d="M20.49 9A9 9 0 0 0 5.64 5.64L1 10M3.51 15A9 9 0 0 0 18.36 18.36L23 14" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
        </svg>
      </button>
    </div>

    <!-- 内容覆盖层 -->
    <div class="content-overlay">
      <slot></slot>
    </div>
  </div>
</template>

<script>
import MapMarker from './MapMarker.vue'

export default {
  name: 'DraggableBackground',
  components: {
    MapMarker
  },
  props: {
    backgroundSrc: {
      type: String,
      required: true
    },
    markers: {
      type: Array,
      default: () => []
    },
    activeMarkerId: {
      type: [String, Number],
      default: null
    },
    sensitivity: {
      type: Number,
      default: 1
    },
    friction: {
      type: Number,
      default: 0.95
    },
    defaultZoom: {
      type: Number,
      default: 1.2,
      validator: (value) => value >= 1 && value <= 2
    },
    minZoom: {
      type: Number,
      default: 1
    },
    maxZoom: {
      type: Number,
      default: 2
    }
  },
  data() {
    return {
      // 拖拽状态
      isDragging: false,
      dragStartX: 0,
      dragStartY: 0,
      dragThreshold: 5, // 拖拽阈值，像素

      // 地图位置和缩放
      mapX: 0,
      mapY: 0,

      // 地图尺寸
      mapWidth: 0,
      mapHeight: 0,
      containerWidth: 0,
      containerHeight: 0,

      // 其他状态
      imageLoaded: false,

      // 惯性滚动
      velocityX: 0,
      velocityY: 0,
      animationId: null,

      // 缩放相关
      currentZoom: 1,
      baseScale: 1,

      // 触摸缩放相关
      lastTouchDistance: 0,
      isMultiTouch: false,
      touchStartZoom: 1,

      // 回弹动画相关
      bounceAnimationId: null,
      isAnimating: false
    }
  },
  computed: {
    mapStyle() {
      // 计算实际显示尺寸（基础尺寸 × 缩放级别）
      const displayWidth = this.mapWidth * this.baseScale * this.currentZoom
      const displayHeight = this.mapHeight * this.baseScale * this.currentZoom

      return {
        transform: `translate3d(${this.mapX}px, ${this.mapY}px, 0)`,
        transformOrigin: '0 0',
        transition: this.isDragging ? 'none' : 'transform 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94)',
        width: `${displayWidth}px`,
        height: `${displayHeight}px`
      }
    },

    // 当前实际显示尺寸
    currentDisplayWidth() {
      if (!this.mapWidth || !this.baseScale || !this.currentZoom) return 0
      return this.mapWidth * this.baseScale * this.currentZoom
    },

    currentDisplayHeight() {
      if (!this.mapHeight || !this.baseScale || !this.currentZoom) return 0
      return this.mapHeight * this.baseScale * this.currentZoom
    }
  },
  mounted() {
    this.initializeMap()
    this.setupEventListeners()
    window.addEventListener('resize', this.handleResize)
  },

  beforeDestroy() {
    this.cleanupEventListeners()
    window.removeEventListener('resize', this.handleResize)
    if (this.animationId) {
      cancelAnimationFrame(this.animationId)
    }
    if (this.bounceAnimationId) {
      cancelAnimationFrame(this.bounceAnimationId)
    }
  },
  methods: {
    initializeMap() {
      this.$nextTick(() => {
        this.updateContainerSize()
      })
    },

    updateContainerSize() {
      if (this.$refs.container) {
        const rect = this.$refs.container.getBoundingClientRect()
        this.containerWidth = rect.width
        this.containerHeight = rect.height
      }
    },

    handleImageLoad() {
      this.imageLoaded = true
      const img = this.$refs.mapLayer?.querySelector('img')
      if (img) {
        this.mapWidth = img.naturalWidth
        this.mapHeight = img.naturalHeight

        // 确保容器尺寸已更新
        this.updateContainerSize()

        // 计算初始缩放，确保图片完全显示
        if (this.containerWidth && this.containerHeight) {
          const scaleX = this.containerWidth / this.mapWidth
          const scaleY = this.containerHeight / this.mapHeight
          this.baseScale = Math.min(scaleX, scaleY, 1)
          this.currentZoom = this.defaultZoom

          console.log('图片加载完成:', {
            mapWidth: this.mapWidth,
            mapHeight: this.mapHeight,
            containerWidth: this.containerWidth,
            containerHeight: this.containerHeight,
            baseScale: this.baseScale,
            defaultZoom: this.defaultZoom
          })
        } else {
          // 如果容器尺寸还没准备好，使用默认值
          this.baseScale = 1
          this.currentZoom = this.defaultZoom
        }

        // 居中显示
        this.centerMap()
      }
    },

    centerMap() {
      // 将地图居中显示
      const displayWidth = this.currentDisplayWidth
      const displayHeight = this.currentDisplayHeight
      this.mapX = (this.containerWidth - displayWidth) / 2
      this.mapY = (this.containerHeight - displayHeight) / 2
    },

    setupEventListeners() {
      document.addEventListener('mousemove', this.handleMouseMove, { passive: false })
      document.addEventListener('mouseup', this.handleMouseUp)
      document.addEventListener('touchmove', this.handleTouchMove, { passive: false })
      document.addEventListener('touchend', this.handleTouchEnd)
    },

    cleanupEventListeners() {
      document.removeEventListener('mousemove', this.handleMouseMove)
      document.removeEventListener('mouseup', this.handleMouseUp)
      document.removeEventListener('touchmove', this.handleTouchMove)
      document.removeEventListener('touchend', this.handleTouchEnd)
    },

    handleResize() {
      console.log('DraggableBackground: 处理尺寸变化')

      // 更新容器尺寸
      this.updateContainerSize()

      // 延迟重新计算布局，确保DOM更新完成
      this.$nextTick(() => {
        // 重新计算基础缩放
        this.calculateBaseScale()

        // 重新居中地图
        this.centerMap()

        console.log('DraggableBackground: 尺寸变化处理完成', {
          containerWidth: this.containerWidth,
          containerHeight: this.containerHeight,
          baseScale: this.baseScale,
          currentZoom: this.currentZoom
        })
      })
    },

    calculateBaseScale() {
      // 计算基础缩放，确保图片完全显示
      if (this.containerWidth && this.containerHeight && this.mapWidth && this.mapHeight) {
        const scaleX = this.containerWidth / this.mapWidth
        const scaleY = this.containerHeight / this.mapHeight
        this.baseScale = Math.min(scaleX, scaleY, 1)

        console.log('重新计算基础缩放:', {
          containerSize: `${this.containerWidth}x${this.containerHeight}`,
          mapSize: `${this.mapWidth}x${this.mapHeight}`,
          scaleX,
          scaleY,
          baseScale: this.baseScale
        })
      } else {
        console.warn('无法计算基础缩放，缺少必要的尺寸信息')
      }
    },

    // 鼠标事件
    handleMouseDown(e) {
      this.startDrag(e)
    },

    handleMouseMove(e) {
      this.moveDrag(e)
    },

    handleMouseUp(e) {
      this.endDrag(e)
    },

    // 触摸事件
    handleTouchStart(e) {
      if (e.touches.length === 2) {
        // 双指触摸开始
        this.isMultiTouch = true
        this.isDragging = false
        this.lastTouchDistance = this.getTouchDistance(e.touches)
        this.touchStartZoom = this.currentZoom
        e.preventDefault()
      } else if (e.touches.length === 1) {
        // 单指触摸开始
        this.isMultiTouch = false
        this.startDrag(e)
      }
    },

    handleTouchMove(e) {
      if (e.touches.length === 2 && this.isMultiTouch) {
        // 双指缩放
        e.preventDefault()
        const currentDistance = this.getTouchDistance(e.touches)
        const scale = currentDistance / this.lastTouchDistance
        const newZoom = Math.max(this.minZoom, Math.min(this.maxZoom, this.touchStartZoom * scale))

        // 获取双指中心点
        const centerX = (e.touches[0].clientX + e.touches[1].clientX) / 2
        const centerY = (e.touches[0].clientY + e.touches[1].clientY) / 2

        // 转换为相对于容器的坐标
        const rect = this.$refs.container.getBoundingClientRect()
        const relativeX = centerX - rect.left
        const relativeY = centerY - rect.top

        this.zoomToPoint(relativeX, relativeY, newZoom)
      } else if (e.touches.length === 1 && !this.isMultiTouch) {
        // 单指拖拽
        this.moveDrag(e)
      }
    },

    handleTouchEnd(e) {
      if (e.touches.length === 0) {
        // 所有手指离开
        this.isMultiTouch = false
        this.endDrag(e)
      } else if (e.touches.length === 1 && this.isMultiTouch) {
        // 从双指变为单指
        this.isMultiTouch = false
        this.isDragging = false
      }
    },

    // 滚轮缩放
    handleWheel(e) {
      e.preventDefault()

      const delta = e.deltaY > 0 ? -0.1 : 0.1
      const rect = this.$refs.container.getBoundingClientRect()
      const centerX = rect.width / 2
      const centerY = rect.height / 2

      this.zoomAtPoint(centerX, centerY, delta)
    },

    // 拖拽核心逻辑
    startDrag(e) {
      e.preventDefault()
      this.isDragging = true

      const point = this.getEventPoint(e)
      this.dragStartX = point.x
      this.dragStartY = point.y

      // 记录当前地图位置
      this.startMapX = this.mapX
      this.startMapY = this.mapY
    },

    moveDrag(e) {
      if (!this.isDragging) return
      e.preventDefault()

      const point = this.getEventPoint(e)
      let deltaX = point.x - this.dragStartX
      let deltaY = point.y - this.dragStartY

      // 检查是否超过拖拽阈值
      const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY)
      if (distance < this.dragThreshold) {
        return // 未超过阈值，不进行拖拽
      }

      // 计算目标位置
      let targetX = this.startMapX + deltaX
      let targetY = this.startMapY + deltaY

      // 添加边界阻力效果
      const displayWidth = this.currentDisplayWidth
      const displayHeight = this.currentDisplayHeight

      // 水平边界阻力
      if (displayWidth > this.containerWidth) {
        const maxX = 0
        const minX = this.containerWidth - displayWidth

        if (targetX > maxX) {
          // 超出右边界，添加阻力
          const overflow = targetX - maxX
          targetX = maxX + overflow * 0.3 // 30% 的阻力
        } else if (targetX < minX) {
          // 超出左边界，添加阻力
          const overflow = minX - targetX
          targetX = minX - overflow * 0.3 // 30% 的阻力
        }
      }

      // 垂直边界阻力
      if (displayHeight > this.containerHeight) {
        const maxY = 0
        const minY = this.containerHeight - displayHeight

        if (targetY > maxY) {
          // 超出上边界，添加阻力
          const overflow = targetY - maxY
          targetY = maxY + overflow * 0.3 // 30% 的阻力
        } else if (targetY < minY) {
          // 超出下边界，添加阻力
          const overflow = minY - targetY
          targetY = minY - overflow * 0.3 // 30% 的阻力
        }
      }

      // 更新地图位置
      this.mapX = targetX
      this.mapY = targetY
    },

    endDrag(e) {
      if (!this.isDragging) return
      e.preventDefault()

      const point = this.getEventPoint(e)
      const deltaX = point.x - this.dragStartX
      const deltaY = point.y - this.dragStartY
      const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY)

      // 只有真正拖拽了才设置为false，否则保持状态以便点击事件判断
      if (distance >= this.dragThreshold) {
        // 拖拽结束后检查是否需要回弹
        this.bounceToConstraints()
      }

      this.isDragging = false
    },

    getEventPoint(e) {
      if (e.touches && e.touches.length > 0) {
        return { x: e.touches[0].clientX, y: e.touches[0].clientY }
      }
      return { x: e.clientX, y: e.clientY }
    },

    getMarkerStyle(marker) {
      return {
        position: 'absolute',
        left: `${marker.x}%`,
        top: `${marker.y}%`,
        transform: 'translate(-50%, -100%)',
        zIndex: 20
      }
    },

    handleMarkerClick(marker) {
      console.log('标记点被点击:', marker)
      // 立即触发事件，不做任何额外检查
      this.$emit('marker-click', marker)
    },

    resetDragState() {
      this.isDragging = false
      this.mapX = 0
      this.mapY = 0
      this.currentZoom = this.defaultZoom
      console.log('地图状态已重置到默认缩放:', this.defaultZoom)
    },

    // 缩放控制方法
    zoomIn() {
      console.log('zoomIn 被调用，当前缩放:', this.currentZoom, '最大缩放:', this.maxZoom)
      if (this.currentZoom >= this.maxZoom) {
        console.log('已达到最大缩放')
        return
      }
      const newZoom = Math.min(this.currentZoom * 1.25, this.maxZoom)
      console.log('准备放大到:', newZoom)
      this.setZoom(newZoom)
    },

    zoomOut() {
      console.log('zoomOut 被调用，当前缩放:', this.currentZoom, '最小缩放:', this.minZoom)
      if (this.currentZoom <= this.minZoom) {
        console.log('已达到最小缩放')
        return
      }
      const newZoom = Math.max(this.currentZoom / 1.25, this.minZoom)
      console.log('准备缩小到:', newZoom)
      this.setZoom(newZoom)
    },

    resetZoom() {
      console.log('resetZoom 被调用，当前缩放:', this.currentZoom, '默认缩放:', this.defaultZoom)
      if (this.currentZoom === this.defaultZoom) {
        console.log('已经是默认缩放')
        return
      }
      console.log('重置缩放到默认值:', this.defaultZoom)
      this.setZoom(this.defaultZoom)
      this.centerMap()
    },

    setZoom(newZoom) {
      // 安全检查
      if (!this.containerWidth || !this.containerHeight || !this.mapWidth || !this.mapHeight) {
        console.warn('容器或地图尺寸未初始化，跳过缩放')
        return
      }

      // 获取容器中心点
      const containerCenterX = this.containerWidth / 2
      const containerCenterY = this.containerHeight / 2

      // 计算当前中心点在地图上的相对位置（0-1之间）
      const currentDisplayWidth = this.currentDisplayWidth
      const currentDisplayHeight = this.currentDisplayHeight

      // 防止除零错误
      const mapCenterRatioX = currentDisplayWidth > 0 ? (containerCenterX - this.mapX) / currentDisplayWidth : 0.5
      const mapCenterRatioY = currentDisplayHeight > 0 ? (containerCenterY - this.mapY) / currentDisplayHeight : 0.5

      // 更新缩放级别
      this.currentZoom = newZoom

      // 计算新的显示尺寸
      const newDisplayWidth = this.mapWidth * this.baseScale * newZoom
      const newDisplayHeight = this.mapHeight * this.baseScale * newZoom

      // 重新计算位置，保持中心点的相对位置不变
      this.mapX = containerCenterX - mapCenterRatioX * newDisplayWidth
      this.mapY = containerCenterY - mapCenterRatioY * newDisplayHeight

      // 限制边界（缩放时使用即时约束，不用回弹）
      this.constrainPositionImmediate()

      // 通知父组件缩放变化
      this.$emit('zoom-change', {
        zoom: newZoom,
        scale: this.baseScale * newZoom
      })

      console.log('缩放完成:', {
        zoom: newZoom,
        displayWidth: newDisplayWidth,
        displayHeight: newDisplayHeight,
        mapX: this.mapX,
        mapY: this.mapY
      })
    },

    zoomAtPoint(x, y, delta) {
      const zoomFactor = delta > 0 ? 1.15 : 0.85
      const newZoom = Math.max(this.minZoom, Math.min(this.maxZoom, this.currentZoom * zoomFactor))

      if (newZoom === this.currentZoom) {
        console.log('缩放已达到极限')
        return
      }

      // 安全检查
      if (!this.mapWidth || !this.mapHeight || !this.baseScale) {
        console.warn('地图尺寸未初始化，跳过缩放')
        return
      }

      // 计算缩放中心点在地图上的相对位置
      const currentDisplayWidth = this.currentDisplayWidth
      const currentDisplayHeight = this.currentDisplayHeight

      // 防止除零错误
      const mapPointRatioX = currentDisplayWidth > 0 ? (x - this.mapX) / currentDisplayWidth : 0.5
      const mapPointRatioY = currentDisplayHeight > 0 ? (y - this.mapY) / currentDisplayHeight : 0.5

      // 更新缩放级别
      this.currentZoom = newZoom

      // 计算新的显示尺寸
      const newDisplayWidth = this.mapWidth * this.baseScale * newZoom
      const newDisplayHeight = this.mapHeight * this.baseScale * newZoom

      // 调整地图位置，使缩放中心点保持在相同的屏幕位置
      this.mapX = x - mapPointRatioX * newDisplayWidth
      this.mapY = y - mapPointRatioY * newDisplayHeight

      // 限制边界（缩放时使用即时约束，不用回弹）
      this.constrainPositionImmediate()

      // 通知父组件缩放变化
      this.$emit('zoom-change', {
        zoom: newZoom,
        scale: this.baseScale * newZoom
      })

      console.log('点位缩放完成:', {
        zoom: newZoom,
        point: { x, y },
        mapX: this.mapX,
        mapY: this.mapY
      })
    },

    // 即时边界约束（用于缩放时）
    constrainPositionImmediate() {
      const displayWidth = this.currentDisplayWidth
      const displayHeight = this.currentDisplayHeight

      // 安全检查
      if (displayWidth <= 0 || displayHeight <= 0) return

      // 如果地图小于容器，居中显示
      if (displayWidth <= this.containerWidth) {
        this.mapX = (this.containerWidth - displayWidth) / 2
      } else {
        // 限制水平边界
        const maxX = 0
        const minX = this.containerWidth - displayWidth
        this.mapX = Math.max(minX, Math.min(maxX, this.mapX))
      }

      if (displayHeight <= this.containerHeight) {
        this.mapY = (this.containerHeight - displayHeight) / 2
      } else {
        // 限制垂直边界
        const maxY = 0
        const minY = this.containerHeight - displayHeight
        this.mapY = Math.max(minY, Math.min(maxY, this.mapY))
      }
    },

    // 计算两个触摸点之间的距离
    getTouchDistance(touches) {
      const dx = touches[0].clientX - touches[1].clientX
      const dy = touches[0].clientY - touches[1].clientY
      return Math.sqrt(dx * dx + dy * dy)
    },

    // 缩放到指定点（用于触摸缩放）
    zoomToPoint(x, y, newZoom) {
      if (newZoom === this.currentZoom) return

      // 安全检查
      if (!this.mapWidth || !this.mapHeight || !this.baseScale) {
        console.warn('地图尺寸未初始化，跳过缩放')
        return
      }

      // 计算缩放中心点在地图上的相对位置
      const currentDisplayWidth = this.currentDisplayWidth
      const currentDisplayHeight = this.currentDisplayHeight

      // 防止除零错误
      const mapPointRatioX = currentDisplayWidth > 0 ? (x - this.mapX) / currentDisplayWidth : 0.5
      const mapPointRatioY = currentDisplayHeight > 0 ? (y - this.mapY) / currentDisplayHeight : 0.5

      // 更新缩放级别
      this.currentZoom = newZoom

      // 计算新的显示尺寸
      const newDisplayWidth = this.mapWidth * this.baseScale * newZoom
      const newDisplayHeight = this.mapHeight * this.baseScale * newZoom

      // 调整地图位置，使缩放中心点保持在相同的屏幕位置
      this.mapX = x - mapPointRatioX * newDisplayWidth
      this.mapY = y - mapPointRatioY * newDisplayHeight

      // 限制边界
      this.constrainPositionImmediate()

      // 通知父组件缩放变化
      this.$emit('zoom-change', {
        zoom: newZoom,
        scale: this.baseScale * newZoom
      })
    },

    // 回弹到边界约束
    bounceToConstraints() {
      const displayWidth = this.currentDisplayWidth
      const displayHeight = this.currentDisplayHeight

      // 安全检查
      if (displayWidth <= 0 || displayHeight <= 0) return

      let targetX = this.mapX
      let targetY = this.mapY
      let needsBounce = false

      // 计算目标位置
      if (displayWidth <= this.containerWidth) {
        targetX = (this.containerWidth - displayWidth) / 2
        if (Math.abs(targetX - this.mapX) > 1) needsBounce = true
      } else {
        const maxX = 0
        const minX = this.containerWidth - displayWidth
        if (this.mapX > maxX) {
          targetX = maxX
          needsBounce = true
        } else if (this.mapX < minX) {
          targetX = minX
          needsBounce = true
        }
      }

      if (displayHeight <= this.containerHeight) {
        targetY = (this.containerHeight - displayHeight) / 2
        if (Math.abs(targetY - this.mapY) > 1) needsBounce = true
      } else {
        const maxY = 0
        const minY = this.containerHeight - displayHeight
        if (this.mapY > maxY) {
          targetY = maxY
          needsBounce = true
        } else if (this.mapY < minY) {
          targetY = minY
          needsBounce = true
        }
      }

      // 如果需要回弹，启动动画
      if (needsBounce) {
        this.animateBounce(targetX, targetY)
      }
    },

    // 回弹动画
    animateBounce(targetX, targetY) {
      if (this.isAnimating) return

      this.isAnimating = true
      const startX = this.mapX
      const startY = this.mapY
      const startTime = performance.now()
      const duration = 400 // 动画持续时间

      const animate = (currentTime) => {
        const elapsed = currentTime - startTime
        const progress = Math.min(elapsed / duration, 1)

        // 使用缓动函数 (easeOutBack)
        const easeOutBack = (t) => {
          const c1 = 1.70158
          const c3 = c1 + 1
          return 1 + c3 * Math.pow(t - 1, 3) + c1 * Math.pow(t - 1, 2)
        }

        const easedProgress = easeOutBack(progress)

        // 计算当前位置
        this.mapX = startX + (targetX - startX) * easedProgress
        this.mapY = startY + (targetY - startY) * easedProgress

        if (progress < 1) {
          this.bounceAnimationId = requestAnimationFrame(animate)
        } else {
          // 动画完成
          this.mapX = targetX
          this.mapY = targetY
          this.isAnimating = false
          this.bounceAnimationId = null
        }
      }

      this.bounceAnimationId = requestAnimationFrame(animate)
    }
  }
}
</script>

<style lang="scss" scoped>
.map-container {
  position: relative;
  width: 100%;
  height: 100vh;
  overflow: hidden;
  background: #EBEFE6;
  cursor: grab;
  user-select: none;

  // 移动端触摸优化
  touch-action: none;
  -webkit-user-select: none;
  -webkit-tap-highlight-color: transparent;
  -webkit-touch-callout: none;

  &:active {
    cursor: grabbing;
  }
}

.map-layer {
  position: absolute;
  will-change: transform;

  img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    pointer-events: none;
    user-select: none;
  }
}

.markers-container {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 50;
}

.marker-wrapper {
  pointer-events: auto;
  cursor: pointer;
  position: relative;
  z-index: 51;
}

.zoom-controls {
  position: absolute;
  top: 20px;
  right: 20px;
  z-index: 1000;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  background: rgba(255, 255, 255, 0.95);
  border-radius: 12px;
  padding: 6px;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
  backdrop-filter: blur(20px);
  border: 1px solid rgba(255, 255, 255, 0.2);
  pointer-events: auto;
}

.zoom-btn {
  width: 44px;
  height: 44px;
  border: none;
  background: transparent;
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  color: #2c3e50;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  position: relative;
  overflow: hidden;

  &:hover:not(:disabled) {
    background: rgba(52, 152, 219, 0.1);
    color: #3498db;
    transform: translateY(-1px);
  }

  &:active:not(:disabled) {
    background: rgba(52, 152, 219, 0.2);
    transform: translateY(0) scale(0.95);
  }

  // 涟漪效果
  &::before {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    width: 0;
    height: 0;
    border-radius: 50%;
    background: rgba(52, 152, 219, 0.3);
    transform: translate(-50%, -50%);
    transition: width 0.3s ease, height 0.3s ease;
  }

  &:active:not(:disabled)::before {
    width: 40px;
    height: 40px;
  }

  &:disabled {
    color: #bdc3c7;
    cursor: not-allowed;
    opacity: 0.5;
  }

  svg {
    pointer-events: none;
    transition: transform 0.2s ease;
  }

  &:hover:not(:disabled) svg {
    transform: scale(1.1);
  }
}

.zoom-level {
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 2px 0;
}

.zoom-text {
  font-size: 12px;
  font-weight: 600;
  color: #2c3e50;
  letter-spacing: 0.5px;
}

.zoom-in {
  border-bottom: 1px solid rgba(0, 0, 0, 0.05);
}

.zoom-out {
  border-top: 1px solid rgba(0, 0, 0, 0.05);
  border-bottom: 1px solid rgba(0, 0, 0, 0.05);
}

.zoom-reset {
  // border-top: 1px solid rgba(0, 0, 0, 0.05);

  svg {
    width: 16px;
    height: 16px;
  }
}

.content-overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 100;
  pointer-events: none;

  * {
    pointer-events: auto;
  }
}

// 移动端适配
@media (max-width: 768px) {
  .zoom-controls {
    top: 15px;
    right: 15px;
    padding: 4px;
    border-radius: 10px;
  }

  .zoom-btn {
    width: 40px;
    height: 40px;
    border-radius: 8px;

    svg {
      width: 16px;
      height: 16px;
    }
  }

  .zoom-level {
    padding: 6px 10px;
    margin: 1px 0;
  }

  .zoom-text {
    font-size: 11px;
  }

  .zoom-reset svg {
    width: 14px;
    height: 14px;
  }
}
</style>
